package com.niiwoo.civet.mobile.controller.withhold;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSON;
import com.niiwoo.civet.account.dto.common.BankCardDTO;
import com.niiwoo.civet.account.dto.response.ApplyWithholdProtocolResponseDTO;
import com.niiwoo.civet.account.dto.response.ConfirmWithholdProtocolResponseDTO;
import com.niiwoo.civet.account.dto.response.GetSimpleUserBankCardResponse;
import com.niiwoo.civet.account.dto.response.WithholdProtocolResultDTO;
import com.niiwoo.civet.account.service.bankcard.BankCardDubboService;
import com.niiwoo.civet.account.service.withholdProtocol.WithholdProtocolDubboService;
import com.niiwoo.civet.base.constant.OrgConstant;
import com.niiwoo.civet.mobile.util.R360RedisService;
import com.niiwoo.civet.mobile.vo.request.withhold.CheckSMSCodeH5RequestVO;
import com.niiwoo.civet.mobile.vo.request.withhold.CheckSMSCodeRequestVO;
import com.niiwoo.civet.mobile.vo.request.withhold.GetSMSCodeH5RequestVO;
import com.niiwoo.civet.mobile.vo.request.withhold.GetSignStatusH5RequestVO;
import com.niiwoo.civet.mobile.vo.response.withhold.CheckSMSCodeResponseVO;
import com.niiwoo.civet.mobile.vo.response.withhold.GetSMSCodeResponseVO;
import com.niiwoo.civet.mobile.vo.response.withhold.GetSignStatusResponseVO;
import com.niiwoo.civet.trade.enums.TradeConfigEnum;
import com.niiwoo.civet.trade.service.configure.TradeConfigDubboService;
import com.niiwoo.civet.user.service.OrganizationDubboService;
import com.niiwoo.tripod.base.component.PrivacyMasks;
import com.niiwoo.tripod.provider.exception.BizException;
import com.niiwoo.tripod.web.annotation.AuthIgnore;
import com.niiwoo.tripod.web.util.PrincipalContext;
import com.niiwoo.tripod.web.vo.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.util.Objects;

/**
 * 签约开通代扣
 * @author: liaozuliang
 * @date: 2018/5/12
 */
@Slf4j
@RestController
@RequestMapping("/withhold/sign")
@Api(tags = "签约开通代扣(廖祖亮)", description = "/withhold/sign")
public class WithholdSignController {

    @Reference(version = "1.0.0")
    private WithholdProtocolDubboService withholdProtocolDubboService;

    @Reference(version = "1.0.0")
    private BankCardDubboService bankCardDubboService;

    @Reference(version = "1.0.0")
    private TradeConfigDubboService tradeConfigDubboService;

    @Reference(version = "1.0.0")
    private OrganizationDubboService organizationDubboService;

    @Autowired
    private PrivacyMasks privacyMasks;

    @Autowired
    private R360RedisService r360RedisService;

    @PostMapping("/getSignStatus")
    @ApiOperation("获取开通代扣签约状态")
    public Result<GetSignStatusResponseVO> getSignStatus() {
        return doGetSignStatus(PrincipalContext.getUserId(), OrgConstant.NIIWOO_ORG_ID);
    }

    @PostMapping("/getSignStatus/h5")
    @ApiOperation("获取开通代扣签约状态")
    @AuthIgnore
    public Result<GetSignStatusResponseVO> getSignStatusH5(@RequestBody @Valid GetSignStatusH5RequestVO requestVO) {
        String userId = validThirdToken(requestVO.getToken(), requestVO.getChannel());
        String orgId = getOrgId(requestVO.getChannel(), requestVO.getOrgCode());
        return doGetSignStatus(userId, orgId);
    }

    /**
     * 获取开通代扣签约状态
     * @param userId
     * @param orgId
     * @return
     */
    private Result<GetSignStatusResponseVO> doGetSignStatus(String userId, String orgId) {
        if (StringUtils.isAnyBlank(userId, orgId)) {
            throw new BizException("USR19117");
        }

        GetSignStatusResponseVO responseVO = new GetSignStatusResponseVO();

        // 代扣签约开关是否开启
        String signWithholdSwitchState = tradeConfigDubboService.selectTradeConfigByEmun(TradeConfigEnum.SMSAUTHFORPAYSTATUS);
        responseVO.setSignSwitchState("1".equals(signWithholdSwitchState) ? 1 : 0);

        BankCardDTO bankCardDTO = null;
        GetSimpleUserBankCardResponse simpleUserBankCardResponse = null;
        try {
            simpleUserBankCardResponse = bankCardDubboService.getSimpleUserBankCard(userId, orgId);
            bankCardDTO = simpleUserBankCardResponse.getBankCard();
        } catch (Exception e) {
            log.error("获取银行卡信息出错：", e);
            if (e instanceof BizException) {
                if (!"ACC10012".equals(((BizException) e).getErrorCode())) {
                    throw e;
                }
            }
        }

        if (bankCardDTO == null || bankCardDTO.getBankCardId() == null) {
            responseVO.setIsBindedCard(0); // 未绑卡
            responseVO.setIsRebindingCard(0);
        } else {
            responseVO.setIsBindedCard(1); // 已绑卡

            // 是否正在换绑银行卡
            Integer isRebindingCard = 0;
            if (simpleUserBankCardResponse.isHasRebindApply()) {
                isRebindingCard = 1;
            }
            responseVO.setIsRebindingCard(isRebindingCard);

            WithholdProtocolResultDTO withholdProtocolResultDTO = withholdProtocolDubboService.getWithholdProtocolResultForLocal(userId, orgId);
            log.info("getSignStatus userId:{}, orgId:{}, withholdProtocolResultDTO: {}", userId, orgId, JSON.toJSONString(withholdProtocolResultDTO));

            if (Boolean.TRUE.equals(withholdProtocolResultDTO.getResult()) && withholdProtocolResultDTO.getExpire() == 1) {
                responseVO.setSignStatus(1); // 已开通代扣
            } else {
                if (Boolean.TRUE.equals(withholdProtocolResultDTO.getResult()) && withholdProtocolResultDTO.getExpire() == 0) {
                    responseVO.setSignStatus(2); // 已失效
                } else {
                    responseVO.setSignStatus(0); // 未开通代扣
                }

                if (bankCardDTO.getBankType().getIsSupportWithhold()) {
                    responseVO.setIsSupportWithhold(1); // 支持代扣
                    String bankCardMobileNo = privacyMasks.maskMobile(bankCardDTO.getMobileNo());
                    responseVO.setBankCardMobileNo(bankCardMobileNo); // 银行卡预留手机号码
                } else {
                    responseVO.setIsSupportWithhold(0); // 不支持代扣
                }
            }
        }

        return Result.with(responseVO);
    }

    @PostMapping("/getSMSCode")
    @ApiOperation("获取短信验证码")
    public Result<GetSMSCodeResponseVO> getSMSCode() {
        return doGetSMSCode(PrincipalContext.getUserId(), OrgConstant.NIIWOO_ORG_ID);
    }

    @PostMapping("/getSMSCode/h5")
    @ApiOperation("获取短信验证码")
    @AuthIgnore
    public Result<GetSMSCodeResponseVO> getSMSCodeH5(@RequestBody @Valid GetSMSCodeH5RequestVO requestVO) {
        String userId = validThirdToken(requestVO.getToken(), requestVO.getChannel());
        String orgId = getOrgId(requestVO.getChannel(), requestVO.getOrgCode());
        return doGetSMSCode(userId, orgId);
    }

    /**
     * 获取短信验证码
     * @param userId
     * @param orgId
     * @return
     */
    private Result<GetSMSCodeResponseVO> doGetSMSCode(String userId, String orgId) {
        if (StringUtils.isAnyBlank(userId, orgId)) {
            throw new BizException("USR19117");
        }

        GetSMSCodeResponseVO responseVO = new GetSMSCodeResponseVO();

        ApplyWithholdProtocolResponseDTO applyWithholdProtocolResponseDTO = withholdProtocolDubboService.applyWithholdProtocol(userId, orgId);
        if (Boolean.TRUE.equals(applyWithholdProtocolResponseDTO.getResult())) {
            responseVO.setIsSuccess(1);
            responseVO.setOrderId(applyWithholdProtocolResponseDTO.getOrderId());
        } else {
            responseVO.setIsSuccess(0);
            responseVO.setErrorMessage(applyWithholdProtocolResponseDTO.getErrorMessage());
            log.error("签约开通代扣-获取短信验证码失败：userId:{}, orgId:{}, {}:{}", userId, orgId, applyWithholdProtocolResponseDTO.getErrorCode(), applyWithholdProtocolResponseDTO.getErrorMessage());
        }

        return Result.with(responseVO);
    }

    @PostMapping("/checkSMSCode")
    @ApiOperation("校验短信验证码")
    public Result<CheckSMSCodeResponseVO> checkSMSCode(@RequestBody @Valid CheckSMSCodeRequestVO requestVO) {
        return doCheckSMSCode(PrincipalContext.getUserId(), OrgConstant.NIIWOO_ORG_ID, requestVO);
    }

    @PostMapping("/checkSMSCode/h5")
    @ApiOperation("校验短信验证码")
    @AuthIgnore
    public Result<CheckSMSCodeResponseVO> checkSMSCodeH5(@RequestBody @Valid CheckSMSCodeH5RequestVO requestVO) {
        String userId = validThirdToken(requestVO.getToken(), requestVO.getChannel());
        String orgId = getOrgId(requestVO.getChannel(), requestVO.getOrgCode());
        return doCheckSMSCode(userId, orgId, requestVO);
    }

    /**
     * 校验短信验证码
     * @param userId
     * @param orgId
     * @param requestVO
     * @return
     */
    private Result<CheckSMSCodeResponseVO> doCheckSMSCode(String userId, String orgId, CheckSMSCodeRequestVO requestVO) {
        if (StringUtils.isAnyBlank(userId, orgId)) {
            throw new BizException("USR19117");
        }

        CheckSMSCodeResponseVO responseVO = new CheckSMSCodeResponseVO();

        ConfirmWithholdProtocolResponseDTO confirmWithholdProtocolResponseDTO = withholdProtocolDubboService.confirmWithholdProtocol(requestVO.getOrderId(), requestVO.getSmsCode());
        if (Boolean.TRUE.equals(confirmWithholdProtocolResponseDTO.getResult())) {
            responseVO.setCheckResult(1);
        } else {
            responseVO.setCheckResult(0);
            log.error("签约开通代扣-校验短信验证码：userId:{}, orgId:{}, {}:{}", userId, orgId, confirmWithholdProtocolResponseDTO.getErrorCode(), confirmWithholdProtocolResponseDTO.getErrorMessage());
        }

        return Result.with(responseVO);
    }

    /**
     * 验证第三方TOKEN，获取userId
     * @param token
     * @param channel
     * @return
     */
    private String validThirdToken(String token, Integer channel) {
        String userId;
        if (channel == null) {
            userId = r360RedisService.verifyTokenAndGetUserId(token);
        } else {
            userId = r360RedisService.verifyTokenAndGetUserId(token, channel);
        }
        return userId;
    }

    /**
     * 获取orgId
     * @param channel
     * @param orgCode
     * @return
     */
    private String getOrgId(Integer channel, String orgCode) {
        String orgId = OrgConstant.NIIWOO_ORG_ID;

        if (Objects.equals(R360RedisService.ThirdPart.ORG.getChannel(), channel)) {
            orgId = organizationDubboService.loadValidOrgId(orgCode);
        }

        return orgId;
    }
}
